package cm.mefobe.android.telecomcost.entities;

import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Date;

import cm.mefobe.android.telecomcost.TelecomCost;

import android.util.Log;

public class Call {
	private String _number;
	private int _duration;
	private Date _date;
	private String _cachedNumberType;
	private String _cachedNumberLabel;
	private String _cachedName;
	private Destination _destination;
	private Day _day;
	private Time _time;

	public Call(String number, Day day, Time time) {
		setNumber(number);
		setDay(day);
		setTime(time);
	}

	public Call() {
	}

	public Call(String number, Date date) {
		setNumber(number);
		setDate(date);
	}

	private void setDate(Date date) {
		_date = date;
	}

	public void setCachedName(String _cachedName) {
		this._cachedName = _cachedName;
	}

	public String getCachedName() {
		return _cachedName;
	}

	public void setCachedNumberLabel(String _cachedNumberLabel) {
		this._cachedNumberLabel = _cachedNumberLabel;
	}

	public String getCachedNumberLabel() {
		return _cachedNumberLabel;
	}

	public void setCachedNumberType(String _cachedNumberType) {
		this._cachedNumberType = _cachedNumberType;
	}

	public String getCachedNumberType() {
		return _cachedNumberType;
	}

	public void setDate(String date) {
		this._date = java.sql.Date.valueOf(date);
	}

	public Date getDate() {
		return _date;
	}

	public void setDuration(int _duration) {
		this._duration = _duration;
	}

	public int getDuration() {
		return _duration;
	}

	public void setNumber(String _number) {
		this._number = _number;
	}

	public String getNumber() {
		return _number;
	}

	private Time getTime() {
		if (_date != null) {
			Log.i("Call","getting time of call of date..." + _date.toLocaleString());
			return _time != null ? _time : new Time(_date.getHours(),
					_date.getMinutes());			
		}

		throw new InvalidParameterException(
				"cannot get the time of this call...date of the call not set");
	}

	public void setTime(Time time) {
		_time = time;
	}

	public Day getDay() {
		if (_date != null) {
			Log.i("Call","getting day of call for date...." + _date.toLocaleString());
			return _day != null ? _day : new Day(_date.getDay() + 1);
		}

		throw new InvalidParameterException(
				"cannot get the day of this call...date of the call not set");
	}

	public void setDay(Day day) {
		_day = day;
	}

	public double getCost() {
		VoiceRate rate = getCallRate();
		if (rate != null) {
			double fees = rate.getFeesPerTimeIntervall(new TimeIntervall(
					TimePeriod.SECOND, getDuration()));
			return fees;
		}

		throw new UnsupportedOperationException(
				"no voice rate defined for the time of this call...");
	}

	public Destination getDestination() {
		ArrayList<Zone> zones = TelecomCost.getDatabaseManager().getZones();
		return getDestination(zones);
	}

	public Destination getDestination(ArrayList<Zone> zones) {
		if (_number != null) {
			if (zones != null) {
				int index = 0;

				while (index < zones.size()) {
					Zone zone = zones.get(index);
					ArrayList<Country> zoneCountries = zone.getCountries();

					int j = 0;

					while (j < zoneCountries.size()) {
						Country country = zoneCountries.get(j);
						if (_number.startsWith(country.getCode())
								|| _number.startsWith("+" + country.getCode())
								|| _number.startsWith("00" + country.getCode())) {
							Log.i("Call", "country " + country.getName()
									+ " found in zone " + zone.getName());
							_destination = new Destination();
							_destination.setZone(zone);
							_destination.setCountry(country);

							if (_number.startsWith(country.getCode())) {
								_number = _number.substring(country.getCode()
										.length());
							}
							if (_number.startsWith("+" + country.getCode())) {
								_number = _number.substring(("+" + country
										.getCode()).length());
							}
							if (_number.startsWith("00" + country.getCode())) {
								_number = _number.substring(("00" + country
										.getCode()).length());
							}

							Log.i("NumberInfoActivity",
									"we look for the provider in the rest of the number..."
											+ _number);

							int k = 0;

							ArrayList<Provider> providers = country
									.getProviders();

							while (k < providers.size()) {
								Provider provider = providers.get(k);
								String[] prefixes = provider.getPrefixes()
										.split(";");

								int n = 0;

								while (n < prefixes.length) {
									if (_number.startsWith(prefixes[n])) {
										Log.i("NumberInfoActivity",
												"we have our provider..."
														+ provider.getName());
										_destination.setProvider(provider);
									}

									n++;
								}

								k++;
							}
						}
						j++;
					}

					index++;
				}
			}
		}

		return _destination;
	}

	public VoiceRate getCallRate() {
		Time time = getTime();
		Log.i("Call","............." + time.toString());
		
		Day day = getDay();
		Log.i("Call","............" + day.getName());

		Log.i("Call", "we get the voice rate for the destination "
				+ _destination.toString() + "...time of call" + time.toString());

		ArrayList<VoiceRate> destinationVoiceRates = _destination
				.getVoiceRates();

		int index = 0;

		while (index < destinationVoiceRates.size()) {
			VoiceRate rate = destinationVoiceRates.get(index);

			if (day.isInDays(rate.getDaysOfWeek())) {
				if ((rate.getStartTime().getHour() <= time.getHour())
						&& (rate.getEndTime().getHour() >= time.getHour())) {
					if (rate.getStartTime().getHour() == time.getHour()) {
						if (rate.getStartTime().getMinute() <= time.getMinute()) {
							return rate;
						}

						continue;
					}

					if (rate.getEndTime().getHour() == time.getHour()) {
						if (rate.getEndTime().getMinute() >= time.getMinute()) {
							return rate;
						}

						continue;
					}

					return rate;
				}
			}

			index++;
		}

		return null;
	}
}
